home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / fst03f.zip / diskio.c < prev    next >
C/C++ Source or Header  |  1996-01-09  |  32KB  |  1,081 lines

  1. /* diskio.c -- Disk/sector I/O for fst
  2.    Copyright (c) 1995-1996 by Eberhard Mattes
  3.  
  4. This file is part of fst.
  5.  
  6. fst is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. fst is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with fst; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #define INCL_DOSDEVIOCTL
  23. #define INCL_DOSDEVICES
  24. #include <os2.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdarg.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <io.h>
  31. #include <fcntl.h>
  32. #include <limits.h>
  33. #include "fst.h"
  34. #include "crc.h"
  35. #include "diskio.h"
  36.  
  37. /* Size of the hash table used for speeding up reading snapshot files. */
  38.  
  39. #define HASH_SIZE       997
  40.  
  41. /* This value marks the end of a hash chain.  It should be an
  42.    `impossible' sector number. */
  43.  
  44. #define HASH_END        0xffffffff
  45.  
  46. /* Method for reading and writing sectors. */
  47.  
  48. enum disk_io_type
  49. {
  50.   DIOT_DISK_DASD,               /* DosRead, DosWrite */
  51.   DIOT_DISK_TRACK,              /* Logical: DSK_READTRACK, DSK_WRITETRACK */
  52.   DIOT_SNAPSHOT,                /* Snapshot file */
  53.   DIOT_CRC                      /* CRC file */
  54. };
  55.  
  56. /* Data for DIOT_DISK_DASD. */
  57.  
  58. struct diskio_dasd
  59. {
  60.   HFILE hf;                     /* File handle */
  61.   char sec_mode;                /* TRUE iff sector mode active */
  62. };
  63.  
  64. /* Data for DIOT_DISK_TRACK. */
  65.  
  66. struct diskio_track
  67. {
  68.   HFILE hf;                     /* File handle */
  69.   ULONG layout_size;            /* Size of structure pointed to by playout */
  70.   ULONG hidden;                 /* Hidden sectors */
  71.   ULONG spt;                    /* Sectors per track */
  72.   ULONG heads;                  /* Number of heads */
  73.   TRACKLAYOUT *playout;         /* Parameter for DSK_READTRACK */
  74.   BYTE *track_buf;              /* Buffer for one track */
  75. };
  76.  
  77. /* Data for DIOT_SNAPSHOT. */
  78.  
  79. struct diskio_snapshot
  80. {
  81.   HFILE hf;                     /* File handle */
  82.   ULONG sector_count;           /* Total number of sectors */
  83.   ULONG *sector_map;            /* Table containing relative sector numbers */
  84.   ULONG *hash_next;             /* Hash chains */
  85.   ULONG version;                /* Format version number */
  86.   ULONG hash_start[HASH_SIZE];  /* Hash chain heads */
  87. };
  88.  
  89. /* Data for DIOT_CRC. */
  90.  
  91. struct diskio_crc
  92. {
  93.   FILE *f;                      /* Stream */
  94.   ULONG version;                /* Format version number */
  95.   crc_t *vec;                   /* See diskio_crc_load() */
  96. };
  97.  
  98. /* DISKIO structure. */
  99.  
  100. struct diskio
  101. {
  102.   enum disk_io_type type;       /* Method */
  103.   ULONG spt;                    /* Sectors per track */
  104.   ULONG total_sectors;          /* Total number of sectors */
  105.   union
  106.     {
  107.       struct diskio_dasd dasd;
  108.       struct diskio_track track;
  109.       struct diskio_snapshot snapshot;
  110.       struct diskio_crc crc;
  111.     } x;                        /* Method-specific data */
  112. };
  113.  
  114. /* This variable selects the method of direct disk I/O to use.
  115.    ACCESS_DASD selects DosRead and DosWrite, ACCESS_LOG_TRACK selects
  116.    DSK_READTRACK and DSK_WRITETRACK for logical disks. */
  117.  
  118. enum access_type diskio_access;
  119.  
  120. /* Non-zero if write access is required. */
  121.  
  122. char write_enable;
  123.  
  124. /* Non-zero if removable disks are allowed. */
  125.  
  126. char removable_allowed;
  127.  
  128. /* Non-zero to ignore failure to lock the disk. */
  129.  
  130. char ignore_lock_error;
  131.  
  132. /* Non-zero to disable locking (FOR TESTING ONLY!). */
  133.  
  134. char dont_lock;
  135.  
  136. /* Type of the save file. */
  137.  
  138. enum save_type save_type;
  139.  
  140. /* This is the save file. */
  141.  
  142. FILE *save_file;
  143.  
  144. /* Name of the save file.  There is no save file if this variable is
  145.    NULL. */
  146.  
  147. const char *save_fname;
  148.  
  149. /* Number of sectors written to the save file. */
  150.  
  151. ULONG save_sector_count;
  152.  
  153. /* Number of elements allocated for save_sector_map. */
  154.  
  155. ULONG save_sector_alloc;
  156.  
  157. /* This table maps logical sector numbers to relative sector numbers
  158.    in the snap shot file, under construction. */
  159.  
  160. ULONG *save_sector_map;
  161.  
  162.  
  163. /* Return the drive letter of a file name, if any, as upper-case
  164.    letter.  Return 0 if there is no drive letter. */
  165.  
  166. static char fname_drive (const char *s)
  167. {
  168.   if (s[0] >= 'A' && s[0] <= 'Z' && s[1] == ':')
  169.     return s[0];
  170.   else if (s[0] >= 'a' && s[0] <= 'z' && s[1] == ':')
  171.     return (char)(s[0]-'a'+'A');
  172.   else
  173.     return 0;
  174. }
  175.  
  176.  
  177. /* Return the currently selected drive as upper-case letter. */
  178.  
  179. static char cur_drive (void)
  180. {
  181.   ULONG drive, map;
  182.  
  183.   if (DosQueryCurrentDisk (&drive, &map) != 0)
  184.     return 0;
  185.   return (char)(drive - 1 + 'A');
  186. }
  187.  
  188.  
  189. /* Obtain access to a disk, snapshot file, or CRC file.  FNAME is the
  190.    name of the disk or file to open.  FLAGS defines what types of
  191.    files are allowed; FLAGS is the inclusive OR of one or more of
  192.    DIO_DISK, DIO_SNAPSHOT, and DIO_CRC.  Open for writing if FOR_WRITE
  193.    is non-zero. */
  194.  
  195. DISKIO *diskio_open (PCSZ fname, unsigned flags, int for_write)
  196. {
  197.   ULONG rc, action, mode, parmlen, datalen, pos, nread, hash, i, ulParm, *map;
  198.   HFILE hf;
  199.   UCHAR data;
  200.   BIOSPARAMETERBLOCK bpb;
  201.   BYTE parm[2];
  202.   int h;
  203.   DISKIO *d;
  204.  
  205.   /* Writing required the -w option.  On the other hand, -w should not
  206.      be used unless writing is requested. */
  207.  
  208.   if (!for_write && write_enable)
  209.     error ("Do not use the -w option for actions that don't write sectors");
  210.   if (for_write && !write_enable)
  211.     error ("Use the -w option for actions that write sectors");
  212.  
  213.   /* Allocate a DISKIO structure. */
  214.  
  215.   d = xmalloc (sizeof (*d));
  216.  
  217.   /* Check for drive letter (direct disk access). */
  218.  
  219.   if (isalpha ((unsigned char)fname[0]) && fname[1] == ':' && fname[2] == 0)
  220.     {
  221.       /* Direct disk access requested.  Check if this is allowed. */
  222.  
  223.       if (!(flags & DIO_DISK))
  224.         error ("A drive name cannot be used for this action");
  225.  
  226.       /* Open a file handle for the logical disk drive. */
  227.  
  228.       if (for_write)
  229.         mode = (OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR
  230.                 | OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT
  231.                 | OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE);
  232.       else
  233.         mode = (OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR
  234.                 | OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT
  235.                 | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY);
  236.       rc = DosOpen (fname, &hf, &action, 0, FILE_NORMAL,
  237.                     OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
  238.                     mode, 0);
  239.       if (rc != 0)
  240.         error ("Cannot open %s (rc=%lu)", fname, rc);
  241.  
  242.       if (!dont_lock)
  243.         {
  244.           /* Attempt to lock the drive. */
  245.  
  246.           parm[0] = 0; parmlen = 1;
  247.           datalen = 1;
  248.           rc = DosDevIOCtl (hf, IOCTL_DISK, DSK_LOCKDRIVE,
  249.                             parm, parmlen, &parmlen,
  250.                             &data, datalen, &datalen);
  251.           if (rc != 0 && (for_write || !ignore_lock_error))
  252.             error ("Cannot lock drive");
  253.           if (rc != 0)
  254.             {
  255.               warning (0, "Cannot lock drive -- proceeding without locking");
  256.               warning_cont (" NOTE: Results are not reliable without locking!");
  257.             }
  258.           else
  259.             {
  260.               /* Issue DSK_REDETERMINEMEDIA to flush the buffers of
  261.                  the file system driver. */
  262.  
  263.               parm[0] = 0; parmlen = 1;
  264.               datalen = 1;
  265.               rc = DosDevIOCtl (hf, IOCTL_DISK, DSK_REDETERMINEMEDIA,
  266.                                 parm, parmlen, &parmlen,
  267.                                 &data, datalen, &datalen);
  268.               if (rc != 0)
  269.                 warning (0, "Cannot flush the buffers of the file system "
  270.                          "dri